package com.zy.sso.client.service;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.client.RestTemplate;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zy.sso.client.component.SpringComponent;
import com.zy.sso.client.dto.BaseUser;
import com.zy.sso.client.dto.find_pwd.FindPwdDTO;
import com.zy.sso.client.dto.login.ClientInfo;
import com.zy.sso.client.dto.login.LoginDTO;
import com.zy.sso.client.dto.logout.LogoutDTO;
import com.zy.sso.client.dto.reset_pwd.ResetPwdDTO;
import com.zy.sso.client.exception.SsoException;
import com.zy.sso.inter.IUserController;

@Service
public class JwtUserService {
	
	private static final Logger logger =  LoggerFactory.getLogger(JwtUserService.class);
	
	@Autowired
	private RestTemplate restTemplate;
	
	@Autowired
	private SpringComponent springComponent;
	
	@Autowired
	private ObjectMapper mapper;
	
	@Value("${sso.fromSys:sso_client_default}")
	private String fromSys;
	
	@Value("${sso.passwordEncoderClass:org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder}")
	private String encoderClass;
	
	@Value("${sso.server.host:http://localhost:8080}")
	private String host;
	
	
	/**
	 * 说明:用户注冊
	 * @param LoginDTO
	 * @return JwtUser
	 * @throws ClassNotFoundException 
	 * @throws JsonProcessingException 
	 * **/
	public BaseUser regist(LoginDTO loginDTO) throws ClassNotFoundException, JsonProcessingException{
		if(logger.isDebugEnabled()) logger.debug(loginDTO.toString());
		loginDTO.setFromSys(fromSys);
		loginDTO.setPasswordEncoder(encoderClass);
		String pass = loginDTO.getPassword();
		PasswordEncoder encode = (PasswordEncoder) springComponent.getBean(Class.forName(encoderClass));
		String hashed  = encode.encode(pass);
		loginDTO.setPassword(hashed);
		logger.info(mapper.writeValueAsString(loginDTO));
		return restTemplate.postForObject(host + IUserController.SSO_REGIST, loginDTO, BaseUser.class);
	}
	
	
	/**
	 * 说明:用户登陆
	 * @param LoginDTO
	 * @return JwtUser
	 * **/
	public BaseUser login(LoginDTO loginDTO){
		return restTemplate.postForObject(host + IUserController.SSO_LOGIN, loginDTO, BaseUser.class);
	}
	
	
	/**
	 * 说明:退出登陆
	 * @param gid
	 * @return JwtUser
	 * **/
	public BaseUser loginOut(String gid,LogoutDTO logoutDto){
		return restTemplate.postForObject(host + IUserController.SSO_LOGINOUT, logoutDto, BaseUser.class,gid);
	}
	
	/**
	 * 说明:找回密码
	 * @param FindPwdDTO
	 * @param account
	 * @return JwtUser
	 * **/
	public BaseUser findPwd(FindPwdDTO findPwdDto,String account){
		return restTemplate.postForObject(host + IUserController.SSO_FIND_PWD, findPwdDto, BaseUser.class,account);
	}
	
	/**
	 * 说明:忘记密码
	 * @param ResetPwdDTO
	 * @param gid
	 * @return JwtUser
	 * **/
	public BaseUser resetPwd(ResetPwdDTO resetPwdDto,String gid){
		resetPwdDto.setPasswordEncoder(encoderClass);
		return restTemplate.postForObject(host + IUserController.SSO_RESET_PWD, resetPwdDto, BaseUser.class,gid);
	}
	
	/**
	 * 说明:获取用户登陆信息
	 * @param gid
	 * @return JwtUser
	 * **/
	public List<ClientInfo> getLoginInfoByGid(String gid){
		ParameterizedTypeReference<List<ClientInfo>> typeRef = new ParameterizedTypeReference<List<ClientInfo>>(){};
		ResponseEntity<List<ClientInfo>> responseEntity = restTemplate.exchange(host + IUserController.SSO_GET_LOGIN_INFO_BY_GID, HttpMethod.POST, null, typeRef,gid);  
		if(!responseEntity.getStatusCode().equals(HttpStatus.OK)){
			logger.error("远程服务调用出差",responseEntity);
			throw new SsoException("没有找到用户的登陆信息");
		}
		return responseEntity.getBody();
	}
	
	/**
	 * 说明:获取用户账户信息(此方法不会走缓存,会直接查询DB,建议使用getAccountInfoByAccount()方法)
	 * @param gid
	 * @return JwtUser
	 * **/
	public BaseUser getAccountInfoByGid(String gid){
		return restTemplate.getForObject(host + IUserController.SSO_GET_ACCOUNT_INFO_BY_GID, BaseUser.class, gid);
	}
	
	/**
	 * 说明:获取用户账户信息
	 * @param account
	 * @return JwtUser
	 * **/
	public BaseUser getAccountInfoByAccount(@PathVariable("account") String account){
		return restTemplate.getForObject(host + IUserController.SSO_GET_ACCOUNT_INFO_BY_ACCOUNT, BaseUser.class, account);
	}

	
}
